package com.kongt.aop;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;


/**
 * 用于将全局需要显示的参数
 *
 * @author kongt 2017年10月23日
 */
//@Component
//@Aspect
public class AopForController {

    /**
     * 在调用方法之前执行
     *
     * @param joinPoint
     */
    @Before(value = "execution(* com.*.controllers..*.*(..))")
    public void before(JoinPoint joinPoint) {
        //获取目标方法的参数信息
        //  Object[] obj = joinPoint.getArgs();
        //AOP代理类的信息   controller信息
        //joinPoint.getThis();

        //代理的目标对象  也就是controller对象
        //joinPoint.getTarget();


        //用的最多 通知的签名
        Signature signature = joinPoint.getSignature();


        //获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        //从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        //如果要获取Session信息的话，可以这样写：
        //HttpSession session = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
        String queryString = request.getQueryString();

    }


    /**
     * 后置返回
     *
     * @param joinPoint
     * @param key       表示返回的值
     */
    @AfterReturning(value = "execution(* com.kongt.controllers..*.*(..))", returning = "key")
    public void afterReturning(JoinPoint joinPoint, Object key) {

    }


    /**
     * 目标方法抛出异常后执行
     *
     * @param joinPoint
     * @param exception
     */
    @AfterThrowing(value = "execution(* com.kongt.controllers..*.*(..))", throwing = "exception")
    public void afterThrowing(JoinPoint joinPoint, Throwable exception) {

    }


    /**
     * 后置最终通知
     *
     * @param joinPoint
     */
    @After(value = "execution(* com.kongt.controllers..*.*(..))")
    public void doAfterAdvice(JoinPoint joinPoint) {
    }

    /**
     * 环绕通知：
     * 环绕通知非常强大，可以决定目标方法是否执行，什么时候执行，执行时是否需要替换方法参数，执行完毕是否需要替换返回值。
     * 环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
     */
    @Around("execution(* com.kongt.controllers..*.*(..))")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) {
        System.out.println("环绕通知的目标方法名：" + proceedingJoinPoint.getSignature().getDeclaringType() + ":" + proceedingJoinPoint.getSignature().getName());
        try {
            Object obj = proceedingJoinPoint.proceed();
            return obj;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }


}
